page.tsx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. "use client";
  2. import GlobalNotify from "@/components/ModalPopup/GlobalNotifyModal";
  3. import {
  4. doClaimShopApi,
  5. getShopInfoApi,
  6. ShopActivityRewardItem,
  7. ShopInfo,
  8. ShopProductItem,
  9. } from "@/api/depositsApi";
  10. import { BtnTypeEnum, BtnTypeMap, ClaimActiveErrorMap } from "@/enums";
  11. import { useRouter } from "@/i18n/routing";
  12. import { formatAmount } from "@/utils/index";
  13. import { Toast } from "antd-mobile";
  14. import clsx from "clsx";
  15. import { useTranslations } from "next-intl";
  16. import { useSearchParams } from "next/navigation";
  17. import React from "react";
  18. import "swiper/css/pagination";
  19. import { Pagination } from "swiper/modules";
  20. import { Swiper, SwiperClass, SwiperSlide } from "swiper/react";
  21. import styles from "./page.module.scss";
  22. const CardPage = () => {
  23. const router = useRouter();
  24. const searchParams = useSearchParams();
  25. const swiperRef = React.useRef<SwiperClass | null>(null);
  26. const [act, setAct] = React.useState(0);
  27. const [amount, setAmount] = React.useState<any>({});
  28. const [visible, setVisible] = React.useState<boolean>(false);
  29. const [shopInfo, setShopInfo] = React.useState<ShopInfo>({} as ShopInfo);
  30. const [loading, setLoading] = React.useState(false);
  31. const [canClaim, setCanClaim] = React.useState<number[]>([]);
  32. const shop_id = React.useMemo(() => {
  33. return Number(searchParams.get("shop_id"));
  34. }, []);
  35. const t = useTranslations();
  36. React.useEffect(() => {
  37. getInfo();
  38. }, []);
  39. const getInfo = async () => {
  40. if (!shop_id) {
  41. setShopInfo({} as ShopInfo);
  42. return;
  43. }
  44. try {
  45. setLoading(true);
  46. const res = await getShopInfoApi({ shop_id });
  47. if (res?.code === 200 && res?.data?.products) {
  48. let actKey = 0;
  49. let canClaimArray: number[] = [];
  50. res.data.products.sort((a: any, b: any) => {
  51. return a.pay - b.pay;
  52. });
  53. const result = res.data.products.map((item: ShopProductItem, idx: number) => {
  54. item.btnType = BtnTypeEnum.DISABLED;
  55. //|| item.is_suss === -1
  56. if (item.days <= 0) {
  57. item.btnType = BtnTypeEnum.DEPOSITE;
  58. }
  59. if (item.days > 0 && item.is_suss === 0) {
  60. canClaimArray.push(idx);
  61. if (!actKey) {
  62. actKey = idx;
  63. }
  64. }
  65. if (item.days > 0 && item.is_suss === 0) {
  66. item.btnType = BtnTypeEnum.CANCLAIM;
  67. }
  68. return item;
  69. });
  70. //自动滚动到第一个买了的商品
  71. setTimeout(() => {
  72. if (actKey) {
  73. setAct(actKey);
  74. }
  75. swiperRef.current?.slideToLoop(actKey, 0, false);
  76. }, 100);
  77. setCanClaim(canClaimArray);
  78. setShopInfo({ ...res.data, products: result || [] });
  79. }
  80. } finally {
  81. setLoading(false);
  82. }
  83. };
  84. const doChange = (type: 1 | -1) => {
  85. if (swiperRef.current) {
  86. if (type === 1) swiperRef.current.slideNext();
  87. if (type === -1) swiperRef.current.slidePrev();
  88. }
  89. };
  90. const redPointInfo = React.useMemo(() => {
  91. const min = Math.min(...canClaim);
  92. const max = Math.max(...canClaim);
  93. const result = {
  94. prev: false,
  95. next: false,
  96. };
  97. if (act > min) {
  98. result.prev = true;
  99. }
  100. if (act < max) {
  101. result.next = true;
  102. }
  103. return result;
  104. }, [act]);
  105. // const data = React.useMemo(() => {
  106. // return [1, 2, 3, 4, 5];
  107. // }, []);
  108. const getActiveInfo = (itemData: ShopProductItem) => {
  109. const amountInfo = itemData.activity_reward.find((item: ShopActivityRewardItem) => {
  110. return item.item_id === 1;
  111. });
  112. const boundsInfo = itemData.activity_reward.find((item: ShopActivityRewardItem) => {
  113. return item.item_id === 2;
  114. });
  115. const bounsAmount = boundsInfo?.amount || 0;
  116. const bounsValue =
  117. boundsInfo?.reward === 1 ? bounsAmount : (bounsAmount / 100) * itemData.pay_value;
  118. const amountAmount = amountInfo?.amount || 0;
  119. const amountValue =
  120. amountInfo?.reward === 1 ? amountAmount : (amountAmount / 100) * itemData.pay_value;
  121. return {
  122. amount: amountValue,
  123. amountRollover: amountInfo?.rollover || 0,
  124. bouns: bounsValue,
  125. bounsRollover: boundsInfo?.rollover || 0,
  126. };
  127. };
  128. const doClaim = async (itemData: ShopProductItem) => {
  129. if (!itemData.id) {
  130. Toast.show({ content: "Missing product ID" });
  131. return;
  132. }
  133. if (itemData.btnType === BtnTypeEnum.DEPOSITE) {
  134. router.push(`/deposit?target_id=${shop_id}`);
  135. return;
  136. }
  137. if (itemData.btnType !== BtnTypeEnum.CANCLAIM) {
  138. return;
  139. }
  140. try {
  141. const res = await doClaimShopApi({
  142. id: itemData.id,
  143. });
  144. if (res.code === 200 && res?.data?.code === 1) {
  145. const amountObj: any = {};
  146. if (res?.data?.reward) {
  147. res?.data?.reward.forEach((item: any) => {
  148. amountObj[`coin_${item.coin_type}`] = formatAmount(item.amount);
  149. });
  150. }
  151. if (res?.data?.extra_reward) {
  152. res?.data?.extra_reward.forEach((item: any) => {
  153. amountObj[`coin_${item.coin_type}`] = formatAmount(
  154. new BigNumber(amountObj[`coin_${item.coin_type}`] || 0)
  155. .plus(item.amount)
  156. .toString()
  157. );
  158. });
  159. }
  160. setAmount(amountObj);
  161. setVisible(true);
  162. getInfo();
  163. } else {
  164. throw new Error(ClaimActiveErrorMap.get(res.data.code) || t(`code.400`));
  165. }
  166. } catch (error: any) {
  167. if (error) {
  168. Toast.show({
  169. content: error.message || error.toString(),
  170. maskClickable: false,
  171. });
  172. }
  173. }
  174. };
  175. return (
  176. <div className={styles.CardPage}>
  177. <div className={styles.top} style={{ minHeight: "300px" }}>
  178. <Swiper
  179. spaceBetween={10}
  180. slidesPerView={1.25}
  181. centeredSlides={true}
  182. onSwiper={(swiper) => {
  183. swiperRef.current = swiper;
  184. }}
  185. onSlideChange={(swiper) => {
  186. setAct(swiper.realIndex);
  187. }}
  188. loop={shopInfo?.products?.length > 3 || false}
  189. modules={[Pagination]}
  190. // loopAdditionalSlides={2}
  191. pagination={{
  192. clickable: true,
  193. }}
  194. >
  195. {!!shopInfo?.products?.length &&
  196. shopInfo?.products.map((item) => {
  197. const itemInfo = getActiveInfo(item);
  198. return (
  199. <SwiperSlide
  200. key={item.id}
  201. className={clsx(styles.swiperSlide, {
  202. [styles.swiperSlideBlue]: item.style === 1,
  203. [styles.swiperSlideGold]: item.style === 3,
  204. })}
  205. >
  206. <div className={styles.swiperItem}>
  207. <div
  208. className={clsx(
  209. "flex flex-row items-center justify-between",
  210. styles.swiperItemTop
  211. )}
  212. >
  213. <div className={clsx(styles.leftContent, "pl-[.1rem]")}>
  214. {shop_id === 4 && "CARTãO DE MêS"}
  215. {shop_id === 3 && "Cartão Semanal"}
  216. </div>
  217. <div
  218. className={clsx(
  219. styles.rightContent,
  220. "pr-[.12rem] pt-[.02rem] text-[.1rem]"
  221. )}
  222. >
  223. {item.days > 0 && "Já foi comprado"}
  224. </div>
  225. </div>
  226. <div className={styles.cardContainerOut}>
  227. <div className={styles.cardContent}>
  228. <div className={styles.cardLeft}>
  229. <div>
  230. <div
  231. className={clsx(
  232. "text-[.11rem] font-bold"
  233. )}
  234. >
  235. Para Recarregar
  236. </div>
  237. <div
  238. className={clsx(
  239. "my-[.04rem] text-[.30rem] font-bold",
  240. styles.money
  241. )}
  242. >
  243. {item.pay_value}R
  244. </div>
  245. </div>
  246. <div className="pb-[.2rem] text-[.15rem] font-bold">
  247. EXTRA {item.desc}%
  248. </div>
  249. </div>
  250. <div className={styles.cardRight}>
  251. <div
  252. className={clsx(
  253. "text-[.1rem]",
  254. styles.cardRightTitle
  255. )}
  256. >
  257. Receba por dia
  258. </div>
  259. <div className="flex-1 text-[.1rem]">
  260. <div className={styles.text_1}>
  261. Numerário
  262. </div>
  263. <div
  264. className={clsx(
  265. "text-[.14rem] font-bold",
  266. styles.text_2
  267. )}
  268. >
  269. {itemInfo.amount}R
  270. </div>
  271. </div>
  272. <div className="flex-1 text-[.1rem]">
  273. <div className={styles.text_1}>Bônus</div>
  274. <div
  275. className={clsx(
  276. "text-[.14rem] font-bold",
  277. styles.text_2
  278. )}
  279. >
  280. {itemInfo.bouns}R
  281. </div>
  282. </div>
  283. </div>
  284. <div className={styles.rili}>
  285. <div className={styles.riliContent}>
  286. <div className="text-[.14rem] font-bold text-[#ac4b31]">
  287. {shop_id === 4 ? "30" : ""}
  288. {shop_id === 3 ? "7" : ""}
  289. </div>
  290. <div className="text-[.12rem] text-[#ac4b31]">
  291. dias
  292. </div>
  293. </div>
  294. </div>
  295. </div>
  296. <div className={styles.lingqu}>
  297. <div
  298. className={clsx(
  299. styles.lingquTop,
  300. "text-[.15rem] font-bold text-[#e4292d]"
  301. )}
  302. >
  303. Receba por dia
  304. </div>
  305. <div className={clsx(styles.lingquContent)}>
  306. <div className={clsx(styles.lingquInfo)}>
  307. {item.btnType === BtnTypeEnum.DEPOSITE && (
  308. <>
  309. <div className="text-center text-[.16rem] font-bold text-[#fffc03]">
  310. Você ainda não comprou
  311. </div>
  312. <div
  313. className={styles.btn2}
  314. onClick={() => doClaim(item)}
  315. >
  316. {BtnTypeMap.get(item.btnType)}
  317. </div>
  318. </>
  319. )}
  320. {item.btnType !== BtnTypeEnum.DEPOSITE && (
  321. <>
  322. <div
  323. className={clsx(
  324. "text-[.18rem] font-bold",
  325. styles.receiveText
  326. )}
  327. >
  328. NUMERÁRIO {itemInfo.amount}R
  329. </div>
  330. <div
  331. className={clsx(
  332. "text-[.18rem]",
  333. styles.receiveText
  334. )}
  335. >
  336. +
  337. </div>
  338. <div
  339. className={clsx(
  340. "text-[.18rem] font-bold",
  341. styles.receiveText
  342. )}
  343. >
  344. BÔNUS {itemInfo.bouns}R
  345. </div>
  346. <div
  347. className={clsx(
  348. "mt-[.08rem] text-[.18rem] font-bold",
  349. styles.receiveText2
  350. )}
  351. >
  352. {item.days} DIAS RESTANTES
  353. </div>
  354. <div
  355. className={clsx(styles.btn, {
  356. [styles.disabled]:
  357. item.btnType ===
  358. BtnTypeEnum.DISABLED,
  359. })}
  360. onClick={() => doClaim(item)}
  361. >
  362. {item.btnType != undefined &&
  363. BtnTypeMap.get(
  364. item.btnType
  365. )}
  366. </div>
  367. </>
  368. )}
  369. </div>
  370. </div>
  371. </div>
  372. </div>
  373. </div>
  374. </SwiperSlide>
  375. );
  376. })}
  377. </Swiper>
  378. <div className={styles.pagation}>
  379. <div
  380. className={clsx(styles.arrow, styles.arrowLeft)}
  381. onClick={() => doChange(-1)}
  382. >
  383. <i className="iconfont icon-xiangyou1"></i>
  384. {redPointInfo.prev && <div className={styles.redCircle}></div>}
  385. </div>
  386. <div
  387. className={clsx(styles.arrow, styles.arrowRight)}
  388. onClick={() => doChange(1)}
  389. >
  390. <i className="iconfont icon-xiangyou1"></i>
  391. {redPointInfo.next && <div className={styles.redCircle}></div>}
  392. </div>
  393. </div>
  394. </div>
  395. <div className={styles.main}>
  396. <div
  397. className="my-[.15rem] cursor-pointer text-right text-[#00deff]"
  398. onClick={() => router.push(`/cardRecord?shop_id=${shop_id}`)}
  399. >
  400. Receba sens registros&gt;
  401. </div>
  402. <div className={styles.config}>
  403. <div className={styles.configItem}>
  404. <div>Recarga</div>
  405. <div>Receba dinheiro diariamente</div>
  406. <div>Receba seu bônus diarianente</div>
  407. <div>Taxa de retirada de dinheiro</div>
  408. <div>Bônus retirada nultiplicação</div>
  409. </div>
  410. {shopInfo?.products?.map((item) => {
  411. const itemInfo = getActiveInfo(item);
  412. return (
  413. <div key={item.id} className={styles.configItem}>
  414. <div>{item.pay_value}</div>
  415. <div>{itemInfo.amount}</div>
  416. <div>{itemInfo.bouns}</div>
  417. <div>{itemInfo.amountRollover}</div>
  418. <div>{itemInfo.bounsRollover}</div>
  419. </div>
  420. );
  421. })}
  422. </div>
  423. <div className={styles.introbox}>
  424. <div className={styles.introContainer}>
  425. <div className={styles.introTitle}>
  426. <span className={styles.introTitleText}>Regras de Atividade</span>
  427. </div>
  428. <ul className={styles.introboxDesc}>
  429. <li>
  430. Recarregue no dia 1 e receba bônus + prêmios emdinheiro diariamente
  431. do mesmo dia até o dia {shop_id === 3 ? "7" : "30"}.
  432. </li>
  433. <li>A retirada diária do prémio do cartão mensal é até às 23h30.</li>
  434. <li>0 cartão mensal é recolhido 1 vez por dia.</li>
  435. <li>
  436. Reemissão automática da parte do prêmio em dinheiro seo cartão
  437. mensal não for recebido no dia, o prêmio de ourocolorido não está
  438. disponível
  439. </li>
  440. </ul>
  441. </div>
  442. </div>
  443. </div>
  444. <GlobalNotify
  445. amount={amount}
  446. visible={visible}
  447. onChange={() => setVisible(false)}
  448. deraction={5000}
  449. ></GlobalNotify>
  450. </div>
  451. );
  452. };
  453. export default CardPage;
  454. CardPage;